package com.media.entrance.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.media.entrance.model.BatchResultDataModel;
import com.media.entrance.model.BatchResultModel;
import com.media.entrance.model.MatchAndResourceModel;
import com.media.entrance.model.MatchInfo;
import com.media.entrance.config.MediaRouterOptions;
import com.media.entrance.websocket.AsyncTask;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
@Slf4j
public class MediaAgentService {

    @Autowired
    private MatchService matchService;

    @Autowired
    private MediaResourceManageService mediaResourceManageService;

    @Autowired
    private MediaRouterOptions mediaRouterOptions;

    @Autowired
    private AsyncTask asyncTask;

    // 坐席批量注册接口
    public BatchResultModel agentsLogin(JSONArray jsonArray) {
        int totalSize = jsonArray.size();
        List<MatchAndResourceModel> success = new ArrayList<>();
        List<MatchAndResourceModel> fail = new ArrayList<>();
        for (Object agentId: jsonArray) {
            String temp = agentId.toString();
            MatchInfo initAgentInfo = matchService.getInitAgentByAgentId(temp);
            MatchInfo agentInfo = matchService.getAgentByAgentId(temp);
            MatchAndResourceModel model = new MatchAndResourceModel();
            if (initAgentInfo == null && agentInfo == null) {
                // 插入一个
                int result = matchService.registerOneAgent(temp);
                if (result == 1) {
                    model.setAgentId(temp);
                    success.add(model);
                } else {
                    model.setReason("insert db fail");
                    model.setAgentId(temp);
                    fail.add(model);
                }
            } else if (initAgentInfo == null) {
                //已经登录了（包含了agentInfo != null）
                model.setReason("already login!");
                model.setAgentId(temp);
                fail.add(model);
            } else if (agentInfo == null) {
                //更新登录状态（包含了initAgentInfo != null）
                if (matchService.updateAgentInitToIdle(temp)) {
                    model.setAgentId(temp);
                    success.add(model);
                } else {
                    model.setReason("update db fail or already login!");
                    model.setAgentId(temp);
                    fail.add(model);
                }
            } else {
                log.error("impossible here because db has two same agentId");
            }
        }
        int size = fail.size();
        BatchResultDataModel data = new BatchResultDataModel();
        data.setSuccess(success);
        data.setFailed(fail);
        log.info("login return data:" + data);
        if (size == totalSize) {
            return new BatchResultModel("fail", size + " agents failed!", data);
        } else {
            return new BatchResultModel("success", size + " agents failed!", data);
        }
    }

    // 坐席批量注销接口
    public BatchResultModel agentsLogout(JSONArray jsonArray) {
        int totalSize = jsonArray.size();
        List<MatchAndResourceModel> success = new ArrayList<>();
        List<MatchAndResourceModel> fail = new ArrayList<>();
        for (Object agentId: jsonArray) {
            String temp = agentId.toString();
            MatchInfo matchInfo = matchService.getAgentByAgentId(temp);
            if (matchInfo == null) {
                MatchAndResourceModel info = new MatchAndResourceModel();
                info.setReason("already logout");
                info.setAgentId(temp);
                fail.add(info);
            } else {
                MatchAndResourceModel model = new MatchAndResourceModel();
                if (matchService.updateAgentIdleToInit(temp)) {
                    model.setAgentId(temp);
                    success.add(model);
                } else {
                    model.setReason("update db fail or status is change!");
                    model.setAgentId(temp);
                    fail.add(model);
                }
            }
        }
        int size = fail.size();
        BatchResultDataModel data = new BatchResultDataModel();
        data.setSuccess(success);
        data.setFailed(fail);
        log.info("logout return data:" + data);
        if (size == totalSize) {
            return new BatchResultModel("fail", size + " agents failed!", data);
        } else {
            return new BatchResultModel("success", size + " agents failed!", data);
        }
    }

    // 坐席轮训接口
    public BatchResultModel getAgentMatchResult(String agentId) {
        MatchInfo matchInfo = matchService.getAgentByAgentId(agentId);
        if (matchInfo == null) {
            log.error("getAgentMatchResult find agentid is null: " + agentId);
            return new BatchResultModel("fail", agentId + " is not login", null);
        }
        BatchResultDataModel data = new BatchResultDataModel();
        MatchAndResourceModel info = new MatchAndResourceModel();
        info.setAgentId(matchInfo.getAgentId());
        switch (matchInfo.getAgentStatus()) {
            case "idle": {
                data.setUnmatch(info);
                log.info("getMatchResult idle return data" + data);
                return new BatchResultModel("success", "agent is idle", data);
            }
            case "ring": {
                info.setDeviceId(matchInfo.getDeviceId());
                info.setRoomId(matchInfo.getRoomId());
                data.setMatching(info);
                log.info("getMatchResult ring return data" + data);
                return new BatchResultModel("success", "agent is ring", data);
            }
            case "busy": {
                // 获取资源信息
                info.setDeviceId(matchInfo.getDeviceId());
                info.setRoomId(matchInfo.getRoomId());
                mediaResourceManageService.getMediaServiceResource(info);
                data.setMatched(info);
                log.info("getMatchResult busy return data" + data);
                return new BatchResultModel("success", "", data);
            }
            case "rest": {
                data.setResting(info);
                log.info("getMatchResult rest return data" + data);
                return new BatchResultModel("success", "agent is idle", data);
            }
            case "pause": {
                data.setPausing(info);
                log.info("getMatchResult pause return data" + data);
                return new BatchResultModel("success", "agent is idle", data);
            }
            default:
                log.error("getMatchResult get status error" + matchInfo);
                return new BatchResultModel("fail", "get status error", null);
        }
    }

    public BatchResultModel updateAgentsStatus(MatchInfo matchInfo) {
        MatchInfo temp = matchService.getAgentByAgentId(matchInfo.getAgentId());
        if (temp == null || temp.getAgentStatus() == null) {
            log.error("updateAgentsStatus find agentid is null: " + matchInfo.getAgentId());
            return new BatchResultModel("fail", "agentid not login", null);
        }
        MatchAndResourceModel model = new MatchAndResourceModel();
        model.setAgentId(matchInfo.getAgentId());
        model.setDeviceId(temp.getDeviceId());
        model.setRoomId(temp.getRoomId());
        BatchResultDataModel data = new BatchResultDataModel();
        String dbStatus = temp.getAgentStatus();
        String tryStatus = matchInfo.getAgentStatus();
        if (dbStatus.equals(tryStatus)) {
            data.getSuccess().add(model);
            return new BatchResultModel("success", "", data);
        } else if ((dbStatus.equals("busy") || dbStatus.equals("ring"))&& tryStatus.equals("idle")) {
            // 匹配结果清空,坐席结束时使用 + 坐席振铃超时时使用
            if (matchService.updateAgentRingOrBusyToIdle(matchInfo.getAgentId())) {
                // 通知客户状态变更
                if (dbStatus.equals("ring")) {
                    asyncTask.agentTimeoutRematch(temp);
                } else {
                    //清理资源redis中的分配信息
                    mediaResourceManageService.releaseMediaServiceResource(temp.getRoomId());
                }
                data.getSuccess().add(model);
                return new BatchResultModel("success", "", data);
            } else {
                data.getFailed().add(model);
                return new BatchResultModel("fail", "update db fail", data);
            }
        } else if (dbStatus.equals("ring") && tryStatus.equals("busy")) {
            if (asyncTask.deviceIdSessionAvailable(temp.getDeviceId())) {
                // 如果设备的websocket断开了
                if (matchService.updateAgentRingToBusy(matchInfo.getAgentId())) {
                    asyncTask.agentBusyInform(temp);
                    data.getSuccess().add(model);
                    return new BatchResultModel("success", "", data);
                } else {
                    model.setReason("update db fail or status is wrong");
                    data.getFailed().add(model);
                    return new BatchResultModel("fail", "", data);
                }
            } else {
                if (matchService.updateAgentRingOrBusyToIdle(matchInfo.getAgentId())) {
                    model.setReason("update db success and current status is idle");
                } else {
                    model.setReason("update db fail or status is wrong");
                }
                data.getFailed().add(model);
                return new BatchResultModel("fail", "deviceId already leave", data);
            }
        } else if (dbStatus.equals("idle") && tryStatus.equals("rest")) {
            if (matchService.updateAgentIdleToRest(matchInfo.getAgentId())) {
                // 打开定时任务，定时任务结束自动从rest变成pause
                data.getSuccess().add(model);
                return new BatchResultModel("success", "rest", data);
            } else {
                data.getFailed().add(model);
                return new BatchResultModel("fail", "update db fail", data);
            }
        } else if (dbStatus.equals("idle") && tryStatus.equals("pause")) {
            if (matchService.updateAgentIdleToPause(matchInfo.getAgentId())) {
                // 如果有定时任务，则关闭
                data.getSuccess().add(model);
                return new BatchResultModel("success", "pause", data);
            } else {
                data.getFailed().add(model);
                return new BatchResultModel("fail", "update db fail", data);
            }
        } else if (dbStatus.equals("rest") && tryStatus.equals("pause")) {
            if (matchService.updateAgentRestToPause(matchInfo.getAgentId())) {
                data.getSuccess().add(model);
                return new BatchResultModel("success", "rest", data);
            } else {
                data.getFailed().add(model);
                return new BatchResultModel("fail", "update db fail", data);
            }
        } else if ((dbStatus.equals("pause") || dbStatus.equals("rest")) && tryStatus.equals("idle")) {
            if (matchService.updateAgentRestOrPauseToIdle(matchInfo.getAgentId())) {
                // 如果有定时任务，则关闭
                data.getSuccess().add(model);
                return new BatchResultModel("success", "", data);
            } else {
                data.getFailed().add(model);
                return new BatchResultModel("fail", "update db fail", data);
            }
        } else {
            model.setReason("No Permit agentId:" + matchInfo.getAgentId() + " status from " +  dbStatus + " change to " + tryStatus);
            data.getSuccess().add(model);
            return new BatchResultModel("fail", "1 agent failed", data);
        }
    }

    //获取某个状态的所有坐席id
    public BatchResultModel getSameStatusAgents(String agentStatus) {
        List<MatchInfo> temp = matchService.getAllAgentsByStatus(agentStatus);
        if (temp.size() == 0) {
            log.error("getSameStatusAgents find agents is none with status: " + agentStatus);
            return new BatchResultModel("fail", "no availvable agent status is " + agentStatus, null);
        }
        BatchResultDataModel data = new BatchResultDataModel();
        for (MatchInfo matchInfo : temp) {
            MatchAndResourceModel model = new MatchAndResourceModel();
            model.setAgentId(matchInfo.getAgentId());
            data.getSuccess().add(model);
        }
        log.info("getSameStatusAgents return data " + data);
        return new BatchResultModel("success", "", data);
    }
    
    // 邀请客户进入房间
    public BatchResultModel inviteOtherAgent(JSONArray jsonArray) {
        List<MatchAndResourceModel> success = new ArrayList<>();
        List<MatchAndResourceModel> fail = new ArrayList<>();
        int totalSize = jsonArray.size();
        for (Object temp: jsonArray) {
            JSONObject input = JSONObject.parseObject(temp.toString(), JSONObject.class);
            if (input.containsKey("agentId") &&
                    input.getString("agentId") != null &&
                    input.containsKey("roomId") &&
                    input.getString("roomId") != null
            ) {
                String targetAgentId = input.getString("agentId");
                String targetRoomId = input.getString("roomId");
                MatchAndResourceModel model = new MatchAndResourceModel();
                model.setAgentId(targetAgentId);
                model.setRoomId(targetRoomId);
                MatchInfo matchinfo = matchService.getAgentByAgentId(targetAgentId);
                if (matchinfo == null) {
                    model.setReason("agentid not login");
                    fail.add(model);
                    continue;
                }
                MatchInfo matchinfo2 = matchService.getAgentByRoomId(targetRoomId);
                if (matchinfo2 == null) {
                    model.setReason("roomId not exist");
                    fail.add(model);
                    continue;
                }
                if (matchService.updateAgentIdleToRing(targetAgentId, matchinfo2.getDeviceId(), targetRoomId)) {
                    success.add(model);
                } else {
                    model.setReason("incert db fail or status is not idle");
                    fail.add(model);
                }
            } else {
                log.error("inviteOther must has agentId and roomId: " +  input.toJSONString());
            }
        }
        int size = fail.size();
        BatchResultDataModel data = new BatchResultDataModel();
        data.setSuccess(success);
        data.setFailed(fail);
        log.info("inviteOtherAgent return data: " + data);
        if (size == totalSize ) {
            return new BatchResultModel("fail", size + " agents failed!", data);
        } else {
            return new BatchResultModel("success", size + " agents failed!", data);
        }
    }

    // 设置排队数
    public BatchResultModel setRouterOptions(JSONObject jsonObject){
        long newSetValue = jsonObject.getLongValue("queueLimit");
        long lastSetValue = mediaRouterOptions.getMaxWaitingLineLimit();
        if (newSetValue == lastSetValue) {
            log.warn("setRouterOptions current value equal last value");
            return new BatchResultModel("fail", "current queueLimit equal to need modify value", null);
        } else {
            mediaRouterOptions.setMaxWaitingLineLimit(newSetValue);
            MatchAndResourceModel match = new MatchAndResourceModel();
            match.setQueueLimit(jsonObject.getLongValue("queueLimit"));
            BatchResultDataModel data = new BatchResultDataModel();
            data.getSuccess().add(match);
            log.info("setRouterOptions return data: " + data);
            return new BatchResultModel("success", "current queueLimit is change from " + lastSetValue + " to " + newSetValue, data);
        }
    }
}
